package com.ding.commander;

import com.ding.common.Constant;
import com.ding.common.Message;

import java.util.logging.Logger;

import static com.ding.common.Constant.STRATEGY_COEXIST;

public class CommanderChannelHolder {

    private static Logger logger = Logger.getLogger("mynat");

    //等待准备时长
    private int waitReadyTimeout = 2000;

    private String newCommandStrategy = Constant.STRATEGY_REJECT;

    public void setNewCommandStrategy(String newCommandStrategy) {
        this.newCommandStrategy = newCommandStrategy;
    }

    public void setWaitReadyTimeout(int waitReadyTimeout) {
        this.waitReadyTimeout = waitReadyTimeout;
    }

    private CPool pool;

    public void setPool(CPool pool) {
        this.pool = pool;
    }

    private int heartbeatTimeout;

    private int heartbeatTime;

    public void setHeartbeatTime(int heartbeatTime) {
        this.heartbeatTime = heartbeatTime;
    }

    //可修改
    public void setHeartbeatTimeout(int heartbeatTimeout) {
        this.heartbeatTimeout = heartbeatTimeout;
    }

    private CommanderChannel commander;

    public CommanderChannel getCommander() {
        return commander;
    }

    private void replace(CommanderChannel holder) {
        CommanderChannel s = this.commander;
        this.commander = holder;
        this.commander.setCommanderChannelHolder(this);

        //引用池
        this.commander.setPool(this.pool);
        this.commander.start(this.heartbeatTime, this.heartbeatTimeout);

        //关闭现有通信
        if (s != null) {
            s.sendMsg(new Message().type(Constant.CLOSE).msg("新的指令通信上线,且指令中心处理策略为[替换]"));
            s.close();
        }
    }

    private void reject(CommanderChannel holder) {

        if (this.commander == null) {
            this.commander = holder;
            this.commander.setCommanderChannelHolder(this);
            this.commander.setPool(this.pool);

            //开始心跳
            this.commander.start(this.heartbeatTime, this.heartbeatTimeout);

        } else {
            holder.sendMsg(new Message().type(Constant.CLOSE).msg("当前指令中心服务指令通信已存在,且指令中心策略为[拒绝]"));
            holder.close();
        }
    }

    private void coexist(CommanderChannel holder) {

        //创建一个指令通道
        if (commander == null) {
            commander = holder;
            commander.setCommanderChannelHolder(this);
            this.commander.setPool(this.pool);
            this.commander.start(this.heartbeatTime, this.heartbeatTimeout);

        } else {
            if (commander instanceof CoexistCommanderChannel) {
                CommanderChannel channel = holder;
                channel.setPool(this.pool);
                channel.start(this.heartbeatTime, this.heartbeatTimeout);
                ((CoexistCommanderChannel) commander).addCommanderChannel(channel);
                this.commander = channel;

            } else {
                //将通道升级为混合型通道
                CoexistCommanderChannel channel = new CoexistCommanderChannel();
                this.commander.setCommanderChannelHolder(null);
                channel.addCommanderChannel(this.commander);
                this.commander = channel;
            }
        }

    }

    public void set(CommanderChannel holder) {
        switch (this.newCommandStrategy) {
            case Constant.STRATEGY_REJECT:
                reject(holder);
                break;
            case Constant.STRATEGY_REPLACE:
                replace(holder);
                break;
            case STRATEGY_COEXIST:
                coexist(holder);
                break;
        }

        if (this.commander != null) {
            if (this.pool.size() < this.pool.getMinSize()) {
                System.out.println("池中通道不足,创建新通道");
                this.commander.sendNewStreamChannel(this.pool.getMinSize() - this.pool.size());
            }
        }

    }

    public boolean sendMsg(Message message) {
        if (this.commander == null) {
            return false;
        }
        this.commander.sendMsg(message);
        return true;
    }


    public void stop() {
        if (this.commander != null) {
            this.commander.close();
        }
    }

    public void removeCommander() {
        this.commander = null;
    }

}
